package com.voicecomm;

import com.voicecomm.audio.AudioProcessor;
import com.voicecomm.audio.AudioRecorder;
import com.voicecomm.config.ApplicationConfig;
import com.voicecomm.database.CommunicationLog;
import com.voicecomm.database.DatabaseManager;
import com.voicecomm.recognition.RealTimeVoiceProcessor;
import com.voicecomm.recognition.VoiceRecognitionService;
import com.voicecomm.recognition.CommEntityExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sound.sampled.LineUnavailableException;
import java.time.LocalDateTime;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 语音通联记录系统主程序
 * 实时识别语音内容并记录通联日志
 * 
 * @author VoiceComm Team
 * @version 1.0.0
 */
public class Main {
    
    private static final Logger logger = LoggerFactory.getLogger(Main.class);
    
    // 系统组件
    private ApplicationConfig config;
    private AudioRecorder audioRecorder;
    private AudioProcessor audioProcessor;
    private VoiceRecognitionService recognitionService;
    private RealTimeVoiceProcessor voiceProcessor;
    private DatabaseManager databaseManager;
    private CommEntityExtractor entityExtractor;
    
    // 当前会话
    private final AtomicReference<CommunicationLog> currentSession = new AtomicReference<>();
    private final AtomicReference<String> currentCallerId = new AtomicReference<>();
    private final AtomicReference<String> currentReceiverId = new AtomicReference<>();
    
    /**
     * 主程序入口
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        Main main = new Main();
        
        try {
            main.initialize();
            main.run();
        } catch (Exception e) {
            logger.error("程序运行异常", e);
            System.exit(1);
        } finally {
            main.cleanup();
        }
    }
    
    /**
     * 初始化系统组件
     */
    private void initialize() throws LineUnavailableException {
        logger.info("正在初始化语音通联记录系统...");
        
        // 加载配置
        config = new ApplicationConfig();
        config.loadFromYaml("application.yml");
        
        if (!config.isValid()) {
            throw new RuntimeException("配置验证失败，请检查配置文件");
        }
        
        // 初始化音频录制器
        audioRecorder = new AudioRecorder();
        audioRecorder.initialize();
        
        // 初始化音频处理器
        audioProcessor = new AudioProcessor();
        
        // 初始化语音识别服务
        recognitionService = new VoiceRecognitionService(
            config.getBaiduAppId(),
            config.getBaiduApiKey(),
            config.getBaiduSecretKey()
        );
        
        // 初始化实时语音处理器
        RealTimeVoiceProcessor.ProcessingConfig processingConfig = 
            new RealTimeVoiceProcessor.ProcessingConfig();
        processingConfig.setFrameSize(config.getAudioConfig().getFrameSize());
        processingConfig.setMaxBufferSize(config.getAudioConfig().getMaxBufferSize());
        processingConfig.setSilenceThreshold(config.getAudioConfig().getSilenceThreshold());
        processingConfig.setMinSilenceDuration(config.getAudioConfig().getMinSilenceDuration());
        processingConfig.setRecognitionInterval(config.getAudioConfig().getRecognitionInterval());
        processingConfig.setVadEnergyThreshold(config.getAudioConfig().getVadEnergyThreshold());
        processingConfig.setMinSpeechDuration(config.getAudioConfig().getMinSpeechDuration());
        processingConfig.setSegmentOnSilence(config.getAudioConfig().isSegmentOnSilence());
        // 直接注入必要参数（去掉反射）
        processingConfig.setTargetRms(config.getAudioConfig().getTargetRms());
        processingConfig.setMinGapBetweenRecognitionsMillis(config.getAudioConfig().getMinGapBetweenRecognitionsMillis());
        processingConfig.setMaxSegmentDurationMillis(config.getAudioConfig().getMaxSegmentDurationMillis());
        
        voiceProcessor = new RealTimeVoiceProcessor(
            audioRecorder, audioProcessor, recognitionService, processingConfig);
        
        // 初始化数据库管理器（可临时关闭）
        if (!config.isDisableDatabase()) {
            databaseManager = new DatabaseManager(config.getDatabaseConfig());
        } else {
            logger.warn("数据库功能已临时禁用：跳过数据库连接与建表");
        }
        
        // 实体抽取器
        entityExtractor = new CommEntityExtractor();

        logger.info("系统初始化完成");
    }
    
    /**
     * 运行主程序
     */
    private void run() {
        Scanner scanner = new Scanner(System.in);
        
        logger.info("语音通联记录系统已启动");
        logger.info("输入 'help' 查看可用命令");
        
        while (true) {
            try {
                System.out.print("\n> ");
                String input = scanner.nextLine().trim();
                
                if (input.isEmpty()) {
                    continue;
                }
                
                String[] parts = input.split("\\s+");
                String command = parts[0].toLowerCase();
                
                switch (command) {
                    case "help":
                        showHelp();
                        break;
                    case "start":
                        startSession(parts);
                        break;
                    case "stop":
                        stopSession();
                        break;
                    case "status":
                        showStatus();
                        break;
                    case "list":
                        listSessions();
                        break;
                    case "quit":
                    case "exit":
                        logger.info("正在退出程序...");
                        return;
                    default:
                        System.out.println("未知命令: " + command + "，输入 'help' 查看可用命令");
                }
                
            } catch (Exception e) {
                logger.error("处理命令时发生错误", e);
                System.out.println("命令执行失败: " + e.getMessage());
            }
        }
    }
    
    /**
     * 显示帮助信息
     */
    private void showHelp() {
        System.out.println("\n=== 语音通联记录系统命令帮助 ===");
        System.out.println("start                           - 开始新的通联会话（自动识别对端呼号）");
        System.out.println("stop                              - 停止当前通联会话");
        System.out.println("status                            - 显示当前状态");
        System.out.println("list                              - 列出所有会话");
        System.out.println("help                              - 显示此帮助信息");
        System.out.println("quit/exit                         - 退出程序");
        System.out.println("\n示例:");
        System.out.println("  start 张三 李四    - 开始张三与李四的通联会话");
        System.out.println("  stop              - 停止当前会话");
    }
    
    /**
     * 开始新的通联会话
     * 
     * @param parts 命令参数
     */
    private void startSession(String[] parts) {
        
        if (currentSession.get() != null) {
            System.out.println("当前已有活跃会话，请先停止当前会话");
            return;
        }
        
        String callerId = config.getMyCallsign();
        String receiverId = "UNKNOWN"; // 启动时未知，对端呼号稍后由识别文本自动填充
        String sessionId = UUID.randomUUID().toString();
        
        // 创建新的通联日志
        CommunicationLog log = new CommunicationLog(sessionId, callerId, receiverId);
        currentSession.set(log);
        currentCallerId.set(callerId);
        currentReceiverId.set(receiverId);
        
        // 保存到数据库（可临时关闭）
        if (!config.isDisableDatabase()) {
            try {
                databaseManager.saveCommunicationLog(log);
                System.out.println("通联会话已开始: " + sessionId);
                System.out.println("呼叫方: " + callerId + ", 接收方: " + receiverId);
            } catch (Exception e) {
                logger.error("保存通联日志失败", e);
                System.out.println("启动会话失败: " + e.getMessage());
                currentSession.set(null);
                return;
            }
        } else {
            System.out.println("通联会话已开始(未持久化): " + sessionId);
            System.out.println("呼叫方: " + callerId + ", 接收方: " + receiverId);
        }
        
        // 启动实时语音处理
        voiceProcessor.startProcessing(this::onRecognitionResult);
        System.out.println("语音识别已启动，开始监听...");
    }
    
    /**
     * 停止当前通联会话
     */
    private void stopSession() {
        CommunicationLog log = currentSession.get();
        if (log == null) {
            System.out.println("当前没有活跃的通联会话");
            return;
        }
        
        // 停止语音处理
        voiceProcessor.stopProcessing();
        
        // 结束会话
        log.endSession();
        
        try {
            if (!config.isDisableDatabase()) {
                // 更新数据库
                databaseManager.updateCommunicationLog(log);
            }
            System.out.println("通联会话已结束: " + log.getSessionId());
            System.out.println("持续时间: " + log.getDurationSeconds() + " 秒");
            System.out.println("识别内容: " + (log.getRecognitionText() != null ? log.getRecognitionText() : "无"));
        } catch (Exception e) {
            logger.error("更新通联日志失败", e);
            System.out.println("停止会话时发生错误: " + e.getMessage());
        } finally {
            currentSession.set(null);
            currentCallerId.set(null);
            currentReceiverId.set(null);
        }
    }
    
    /**
     * 显示当前状态
     */
    private void showStatus() {
        CommunicationLog log = currentSession.get();
        
        System.out.println("\n=== 系统状态 ===");
        System.out.println("语音处理状态: " + (voiceProcessor.isProcessing() ? "运行中" : "已停止"));
        System.out.println("数据库连接: " + (config.isDisableDatabase() ? "已禁用" : (databaseManager != null && databaseManager.isConnectionHealthy() ? "正常" : "异常")));
        
        if (log != null) {
            System.out.println("当前会话: " + log.getSessionId());
            System.out.println("呼叫方: " + log.getCallerId());
            System.out.println("接收方: " + log.getReceiverId());
            System.out.println("开始时间: " + log.getStartTime());
            System.out.println("持续时间: " + log.getCurrentDuration() + " 秒");
            System.out.println("已识别内容: " + (log.getRecognitionText() != null ? log.getRecognitionText() : "无"));
        } else {
            System.out.println("当前会话: 无");
        }
        
        System.out.println("已处理音频帧数: " + voiceProcessor.getProcessedFrames());
    }
    
    /**
     * 列出所有会话
     */
    private void listSessions() {
        try {
            if (config.isDisableDatabase()) {
                System.out.println("\n=== 最近7天的通联会话 ===");
                System.out.println("数据库功能已临时禁用，无法读取会话记录");
                return;
            }
            // 获取最近7天的会话
            LocalDateTime endTime = LocalDateTime.now();
            LocalDateTime startTime = endTime.minusDays(7);
            
            var sessions = databaseManager.findByDateRange(startTime, endTime);
            
            System.out.println("\n=== 最近7天的通联会话 ===");
            if (sessions.isEmpty()) {
                System.out.println("没有找到会话记录");
            } else {
                System.out.printf("%-20s %-10s %-10s %-20s %-8s %-50s%n", 
                               "会话ID", "呼叫方", "接收方", "开始时间", "持续时间", "识别内容");
                System.out.println("-------------------------------------------------------");
                
                for (CommunicationLog session : sessions) {
                    String content = session.getRecognitionText();
                    if (content != null && content.length() > 50) {
                        content = content.substring(0, 47) + "...";
                    }
                    
                    System.out.printf("%-20s %-10s %-10s %-20s %-8d %-50s%n",
                                   session.getSessionId().substring(0, Math.min(20, session.getSessionId().length())),
                                   session.getCallerId(),
                                   session.getReceiverId(),
                                   session.getStartTime().toString().substring(0, 19),
                                   session.getDurationSeconds() != null ? session.getDurationSeconds() : 0,
                                   content != null ? content : "无");
                }
            }
        } catch (Exception e) {
            logger.error("列出会话失败", e);
            System.out.println("列出会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 处理识别结果回调
     * 
     * @param result 识别结果
     */
    private void onRecognitionResult(VoiceRecognitionService.RecognitionResult result) {
        if (result.isSuccess() && !result.getText().trim().isEmpty()) {
            CommunicationLog log = currentSession.get();
            if (log != null) {
                // 追加识别文本
                log.appendRecognitionText(result.getText());
                log.setConfidenceScore(result.getConfidence());

                // 实体抽取：根据识别文本补全呼号/QTH/设备/信号/天线/高度
                try {
                    entityExtractor.extractAndMerge(result.getText(), config.getMyCallsign(), log);
                } catch (Exception e) {
                    logger.warn("实体抽取失败", e);
                }
                
                // 实时显示识别结果
                logger.info("[识别]:{} (置信度: {}) ，呼号：{}", result.getText() ,String.format("%.2f", result.getConfidence()),log.getReceiverId());

                // 异步更新数据库（可临时关闭，包含新增结构化字段）
                if (!config.isDisableDatabase()) {
                    try {
                        databaseManager.updateCommunicationLog(log);
                    } catch (Exception e) {
                        logger.error("更新通联日志失败", e);
                    }
                }
            }
        }
    }
    
    
    /**
     * 清理资源
     */
    private void cleanup() {
        logger.info("正在清理系统资源...");
        
        try {
            // 停止当前会话
            if (currentSession.get() != null) {
                stopSession();
            }
            
            // 关闭语音处理器
            if (voiceProcessor != null) {
                voiceProcessor.cleanup();
            }
            
            // 关闭音频录制器
            if (audioRecorder != null) {
                audioRecorder.cleanup();
            }
            
            // 关闭语音识别服务
            if (recognitionService != null) {
                recognitionService.shutdown();
            }
            
            // 关闭数据库连接（可临时关闭）
            if (!config.isDisableDatabase() && databaseManager != null) {
                databaseManager.close();
            }
            
        } catch (Exception e) {
            logger.error("清理资源时发生错误", e);
        }
        
        logger.info("系统资源清理完成");
    }
}
